#include <QApplication>
#include <QMessageBox>
#include <QProcess>
#include <QLibrary>
#include <QDir>

#include <QSystemSemaphore>
#include <QSharedMemory>

#include "global.h"

typedef void (*ShowDlg)(char *appkey, char* appsecret, char *identity);
typedef int (*ShowRegister)(QString stFile, QString msc, QString& serialCode);

const QString identity = QObject::tr("master");

int main( int argc, char **argv ) {
  QApplication app( argc, argv );
  // log start
  writeLog("\n", true);
  writeLog("Start...");

  // set share memory
  QSystemSemaphore sema("QObject",1,QSystemSemaphore::Open);
  sema.acquire();
  QSharedMemory mem("SystemObject");
  if (!mem.create(1)) {
    QMessageBox::information(NULL, QObject::tr("提示"), QObject::tr("程序已运行"));
    sema.release();
    return 0;
  }
  sema.release();
  writeLog("Allocate share memory success...");


  // set global path
  QDir dir;
  gloPath = dir.currentPath();
  datFile = gloPath + "/face.dat";
  cmdFile = gloPath + "/command.bat";
  stoPath = gloPath + "/storage";
  logFile = stoPath + "/face.log";
  configFile = stoPath + "/config.ini";
  settingFile = stoPath + "/setting.ini";

  // check and create storage directory
  QDir stoDir(stoPath);
  if (!stoDir.exists()) {
    stoDir.mkdir(stoPath);
  }

  // check config file & check if updated
  bool bRet;
  QFile cnfFile(configFile);
  if (!cnfFile.exists()) {
    writeFile(&configFile, "[config]\n");
    writeFile(&configFile, "curver=v2.0.0\n");
    writeFile(&configFile, "newver=v2.0.0\n");

  } else {
    QString curver = readSetting(&configFile, "config", "curver");
    QString newver = readSetting(&configFile, "config", "newver");

    // new version exists & replace it
    if (newver != "" && curver != newver) {

      bRet = copyDirectoryFiles(stoPath + "/" + newver, gloPath);
      if (bRet) {
        writeSetting(&configFile, "config", "curver", newver);
      } else {
        QMessageBox::information(NULL, QObject::tr("提示"), QObject::tr("更新系统失败, 请稍后再试"));
        return 0;
      }

      QFile commandFile(cmdFile);
      if (commandFile.exists()) {
        QByteArray ba = cmdFile.toLatin1();  
        char *mm = ba.data();  
        system(mm);
        return 0;
      }
    }
  }

  QFile setFile(settingFile);
  if (!setFile.exists()) {
    writeFile(&settingFile, "[config]\n");
    writeFile(&settingFile, "identity="+identity+"\n");
    writeFile(&settingFile, "token=abcdefghijklmnopqrstuvwxyz123456\n");
  }

  // reach machine code
  machineCode = getMD5(getWMIHWInfo());
  QString saveCode = getMD5("机器码:" + machineCode);

  // check register info & register
  QFile file(datFile);
  if (!file.exists()) {
    QLibrary facegateLib(QObject::tr("facegate.dll"));
    if (facegateLib.load()) {
      writeLog("Start Register...");
      ShowRegister showRegister = (ShowRegister)facegateLib.resolve("showRegister");
      if (showRegister) {
        QString serialCode;
        int iRet = showRegister(settingFile, machineCode, serialCode);

        // register success
        if (QDialog::Accepted == iRet) {
          writeFile(&datFile, saveCode);
          writeFile(&datFile, serialCode);

        } else {
          return 0;
        }
      }
    } else {
      writeLog("Load facegate dll failed...");
      QMessageBox::information(NULL, QObject::tr("提示"), QObject::tr("加载识别程序失败, 请联系客服"));
      return 0;
    }
  } else {
    // check saveCode
    if (QString::compare(saveCode, readFile(&datFile, 0, 32), Qt::CaseSensitive) != 0) {
      QFile::remove(datFile);
      return 0;
    }

  }

  // calculate keypair
  appkey = getMD5("密键:" + readFile(&datFile, 32, 16));
  appsecret = getMD5("密钥:"+appkey + machineCode);

  // remove command file
  QFile::remove(cmdFile);

  // load facereco dll
  QLibrary mylib(QObject::tr("facerecoDll.dll"));
  if(mylib.load()) {
    writeLog("Start Main Window...");
    ShowDlg showDlg = (ShowDlg)mylib.resolve("ShowDlg");
    if(showDlg) {
      // app.exit(0);
      showDlg(appkey.toUtf8().data(), appsecret.toUtf8().data(), identity.toUtf8().data());
    }
    mylib.unload();
  } else {
    writeLog("Load facereco dll failed...");
    QMessageBox::information(NULL, QObject::tr("提示"), QObject::tr("加载识别程序失败, 请联系客服"));
    return 0;
  }


  return 0;
}
